From df1231853ed8a8d6db3f4f6640a624be2f101439 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 10 Nov 2005 15:03:33 +0100 Subject: [PATCH] When creating exception/interrupt stack frames for a guest, set saved eflags.IF to !saved_upcall_mask. This allows the guest to test interrupts-enabled in the interrupted context in the same way as when running natively. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c | 2 +- linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c | 3 +-- linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c | 2 +- linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c | 2 +- xen/arch/x86/domain.c | 2 +- xen/arch/x86/x86_32/entry.S | 7 ++++++- xen/arch/x86/x86_64/entry.S | 12 +++++++++--- xen/include/public/arch-x86_32.h | 2 +- xen/include/public/arch-x86_64.h | 2 +- 9 files changed, 22 insertions(+), 12 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c index f1ef4e21e2..5ad8d1b273 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/traps.c @@ -650,7 +650,7 @@ fastcall void do_int3(struct pt_regs *regs, long error_code) static inline void conditional_sti(struct pt_regs *regs) { - if ((uint8_t)(regs->xcs >> 16) == 0) + if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) local_irq_enable(); } diff --git a/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c b/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c index 7f8c79829c..269003960e 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c @@ -300,9 +300,8 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code) if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, SIGSEGV) == NOTIFY_STOP) return; - /* It's safe to allow irq's after cr2 has been saved */ - if ((uint8_t)(regs->xcs >> 16) == 0) + if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) local_irq_enable(); tsk = current; diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c index 80ea2d8cf5..07a8a35dcc 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c @@ -89,7 +89,7 @@ int register_die_notifier(struct notifier_block *nb) static inline void conditional_sti(struct pt_regs *regs) { - if ((uint8_t)(regs->cs >> 32) == 0) + if (regs->eflags & X86_EFLAGS_IF) local_irq_enable(); } diff --git a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c index 54e1eeadcc..1c76222721 100644 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c @@ -351,7 +351,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) SIGSEGV) == NOTIFY_STOP) return; - if (likely((uint8_t)(regs->cs >> 32) == 0)) + if (likely(regs->eflags & X86_EFLAGS_IF)) local_irq_enable(); if (unlikely(page_fault_trace)) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index a37643a5d5..b20a4accc8 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -647,7 +647,7 @@ long do_switch_to_user(void) regs->rip = stu.rip; regs->cs = stu.cs | 3; /* force guest privilege */ - regs->rflags = stu.rflags; + regs->rflags = (stu.rflags & ~(EF_IOPL|EF_VM)) | EF_IE; regs->rsp = stu.rsp; regs->ss = stu.ss | 3; /* force guest privilege */ diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 5712895a65..3d93596dc3 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -156,7 +156,7 @@ ENTRY(vmx_asm_vmexit_handler) * By this time, all the setups in the VMCS must be complete. */ .if \launch - /* VMLUANCH */ + /* VMLAUNCH */ .byte 0x0f,0x01,0xc2 pushf call vm_launch_fail @@ -394,7 +394,12 @@ FLT14: movl %eax,%gs:(%esi) shll $16,%eax # Bits 16-23: saved_upcall_mask movw UREGS_cs+4(%esp),%ax # Bits 0-15: CS FLT15: movl %eax,%gs:4(%esi) + test $0x00FF0000,%eax # Bits 16-23: saved_upcall_mask + setz %ch # %ch == !saved_upcall_mask movl UREGS_eflags+4(%esp),%eax + andl $~X86_EFLAGS_IF,%eax + shlb $1,%ch # Bit 9 (EFLAGS.IF) + orb %ch,%ah # Fold EFLAGS.IF into %eax FLT16: movl %eax,%gs:8(%esi) test $TBF_EXCEPTION_ERRCODE,%cl jz 1f diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 90e485570b..27af3eb931 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -352,8 +352,6 @@ create_bounce_frame: FLT2: movq %rax,32(%rsi) # SS movq UREGS_rsp+8(%rsp),%rax FLT3: movq %rax,24(%rsi) # RSP - movq UREGS_eflags+8(%rsp),%rax -FLT4: movq %rax,16(%rsi) # RFLAGS movq VCPU_vcpu_info(%rbx),%rax pushq VCPUINFO_upcall_mask(%rax) testb $TBF_INTERRUPT,%cl @@ -362,7 +360,15 @@ FLT4: movq %rax,16(%rsi) # RFLAGS popq %rax shlq $32,%rax # Bits 32-39: saved_upcall_mask movw UREGS_cs+8(%rsp),%ax # Bits 0-15: CS -FLT5: movq %rax,8(%rsi) # CS/saved_upcall_mask +FLT4: movq %rax,8(%rsi) # CS / saved_upcall_mask + shrq $32,%rax + testb $0xFF,%al # Bits 0-7: saved_upcall_mask + setz %ch # %ch == !saved_upcall_mask + movq UREGS_eflags+8(%rsp),%rax + andq $~X86_EFLAGS_IF,%rax + shlb $1,%ch # Bit 9 (EFLAGS.IF) + orb %ch,%ah # Fold EFLAGS.IF into %eax +FLT5: movq %rax,16(%rsi) # RFLAGS movq UREGS_rip+8(%rsp),%rax FLT6: movq %rax,(%rsi) # RIP testb $TBF_EXCEPTION_ERRCODE,%cl diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index 7b09dc67a9..b11c482118 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -90,7 +90,7 @@ typedef struct cpu_user_regs { uint16_t cs; uint8_t saved_upcall_mask; uint8_t _pad0; - uint32_t eflags; + uint32_t eflags; /* eflags.IF == !saved_upcall_mask */ uint32_t esp; uint16_t ss, _pad1; uint16_t es, _pad2; diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index a0ec55ede1..e53df602ea 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -154,7 +154,7 @@ typedef struct cpu_user_regs { uint16_t cs, _pad0[1]; uint8_t saved_upcall_mask; uint8_t _pad1[3]; - __DECL_REG(flags); + __DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */ __DECL_REG(sp); uint16_t ss, _pad2[3]; uint16_t es, _pad3[3]; -- 2.30.2